package com.penglecode.netty.client;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.net.SocketAddress;

import com.penglecode.netty.RequestEntity;
import com.penglecode.netty.ResponseEntity;
import com.penglecode.netty.util.DateTimeUtils;

public class NettyProxy implements InvocationHandler {

	private NettyClient nettyClient;
	
	private Class<?> interfaceClass;
	
	public NettyProxy(NettyClient nettyClient, Class<?> interfaceClass) {
		super();
		this.nettyClient = nettyClient;
		this.interfaceClass = interfaceClass;
	}
	
	public Class<?> getInterfaceClass() {
		return interfaceClass;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String uri = nettyClient.getRemoteServerAddress().toString();
		String methodName = method.getName();
	    Class<?> []params = method.getParameterTypes();
	    if(methodName.equals("equals") && params.length == 1){
	    	return false;
	    }else if(methodName.equals("hashCode") && params.length == 0){
	    	return new Integer(uri.hashCode());
	    }else if(methodName.equals("toString") && params.length == 0){
	    	return "NettyProxy[" + uri + "]";
	    }else if(methodName.equals("clone") && params.length == 0){
	    	return null;
	    }else if(methodName.equals("finalize") && params.length == 0){
	    	throw new UnsupportedOperationException("can't invoke remote object's method[finalize]!");
	    }else if(methodName.equals("getClass") && params.length == 0){
	    	return getInterfaceClass();
	    }else if(methodName.equals("notify") && params.length == 0){
	    	throw new UnsupportedOperationException("can't invoke remote object's method[notify]!");
	    }else if(methodName.equals("notifyAll") && params.length == 0){
	    	throw new UnsupportedOperationException("can't invoke remote object's method[notifyAll]!");
	    }else if(methodName.equals("wait")){
	    	throw new UnsupportedOperationException("can't invoke remote object's method[wait]!");
	    }
	    SocketAddress localSocketAddress = nettyClient.getLocalAddress();
	    String interfaceClassName = interfaceClass.getName();
	    String fullMethodName = method.toGenericString();
	    fullMethodName = fullMethodName.substring(fullMethodName.indexOf(interfaceClassName));
	    RequestEntity requestEntity = new RequestEntity(String.valueOf(System.nanoTime()), nettyClient.getPrivateKey(), interfaceClassName, method.getName(), fullMethodName, args, localSocketAddress == null ? null : localSocketAddress.toString(), DateTimeUtils.getCurrentDateTime());
		ResponseEntity response = nettyClient.execute(requestEntity);
		return response;
	}


}
